/*
* @Date: 2021/1/1
* @Author: XueChengwu <xuechengwu@erayt.com>
* @Copyright: 2015-2019 Erayt, Inc.
* @Description: If you have some questions, please contact: xuechengwu@erayt.com.
*/
import React from 'react';
import MiniLayer from '@/ochart/react/Minite/bu/MiniLayer';
import AxisLayer from '@/ochart/layer/AxisLayer';
import Canvas from '@/ochart/core/Canvas';
import Point from "ochart/core/Point";
import PriceLayer from './bu/PriceLayer';
import OChart from "ochart/core/OChart";
import Circle from 'ochart/base/Circle';
import ScaleAction from 'ochart/action/ScaleAction';

export default class extends React.Component {
  constructor(props) {
    super(props);
    this.chartRef = React.createRef();
  }

  updateRate = ({ midRate }) => {
    const { data = [] } = this.miniLayer;
    const label = new Date().getTime();
    if (data.length <= 1) {
      data.push({
        value: midRate,
        label,
      });
    } else {
      const vo = data[data.length - 2];
      if (label - vo.label < 60000) {
        data[data.length - 1] = {
          ...data[data.length - 1],
          label,
          value: midRate,
        }
      } else {
        data.push({
          label,
          value: midRate,
        });
      }
    }
    this.miniLayer.data = data;
    this.circleAction.runAction(new ScaleAction(2, 1.2, 1.2));
    this.miniLayer.make();
    this.canvas.paint();
  }

  componentWillReceiveProps (nextProps, nextContext) {
    const { data = [], totalCount, baseLine } = nextProps;
    if (
      this.props.data !== data
      || this.props.totalCount !== totalCount
      || this.props.baseLine !== baseLine
    ) {
      this.miniLayer.data = data;
      this.miniLayer.count = totalCount;
      this.miniLayer.baseLine = baseLine;
      this.miniLayer.make();
      this.canvas.paint();
    }
  }

  componentDidMount() {
    const {
      style = { color: '#333333', axisColor: '#333333', xFontSize: 20 },
      data = [],
      totalCount = 24 * 60 * 60,
      baseLine = 0,
      id,
    } = this.props;
    const xFontSize = style.xFontSize || 20;
    this.canvas = new Canvas({
      ele: this.chartRef.current,
      canAction: false,
    });
    this.axisLayer = new AxisLayer(this.canvas, {
      yAxisType: AxisLayer.AxisType.NUMBER, // y轴为数值型
      xAxisType: AxisLayer.AxisType.LABEL,  // x轴时间为字符型
      xAxisGraduations: style.xAxis || 3,   // 网格5列
      yAxisGraduations: style.yAxis || 5,   // 网格5行
      xAxisPosition: AxisLayer.AxisPosition.BLOCK,  // X轴坐标不计算
      yAxisPosition: AxisLayer.AxisPosition.INNER,  // Y轴坐标计算
      yAxisRender: (value) => {
        const enob = style.enob || 2;
        return {
          text: Number(value).toFixed(enob),
          size: Number(style.yFontSize || 20),
          color: style.axisColor || '#999999',
          font: style.fontFamily || '微软雅黑',
        };
      },
      xAxisRender: (label) => {
        return {
          text: label,
          size: xFontSize,
          color: style.axisColor || '#999999',
          font: style.fontFamily || '微软雅黑',
        };
      },
      color: '#999999',
    });
    this.currentPrice = new PriceLayer(this.canvas, {});
    this.circle = new Circle(this.canvas, {
      radius: 6,
      type: Circle.TYPE.FILL,
      color: style.color,
    });
    this.circleAction = new Circle(this.canvas, {
      radius: 6,
      type: Circle.TYPE.FILL,
      color: style.color,
      alpha: 0.6,
    });
    this.miniLayer = new MiniLayer(this.canvas, {
      color: style.color,
      height: (this.canvas.height - xFontSize) * 0.8, // 预留20%的空白空间
      width: this.canvas.width,
      position: new Point(0, xFontSize * 0.9 + 0.1 * this.canvas.height), // 预留的10% + 坐标的高度
      count: totalCount,
      baseY: 0,
      baseLine,
      onMaked: ({ xStep, yStep, baseLine, pcg, maxIndex, minIndex, max, min }) => {
        let yAxisMax = max + (this.canvas.height - xFontSize) * 0.1 / yStep;
        let yAxisMin = min - (this.canvas.height - xFontSize) * 0.1 / yStep;
        this.axisLayer.yAxisMin = yAxisMin;
        this.axisLayer.yAxisMax = yAxisMax;
        const maxPointY = (max - baseLine) * yStep + this.miniLayer.height / 2 + this.miniLayer.position.y;
        const maxPointX = maxIndex / this.miniLayer.count * this.miniLayer.width + this.miniLayer.position.x;
        const minPointY = (min - baseLine) * yStep + this.miniLayer.height / 2 + this.miniLayer.position.y;
        const minPointX = minIndex / this.miniLayer.count * this.miniLayer.width + this.miniLayer.position.x;
        this.currentPrice.maxInfo = {
          point: {
            x: maxPointX,
            y: maxPointY,
          },
          value: max,
          color: '#D42922',
        };
        this.currentPrice.minInfo = {
          point: {
            x: minPointX,
            y: minPointY,
          },
          value: min,
          color: '#00AE00',
        };
        this.currentPrice.currentInfo = {
          point: {
            x: this.miniLayer.data.length / this.miniLayer.count * this.miniLayer.width + this.miniLayer.position.x,
            y: (this.miniLayer.data[this.miniLayer.data.length - 1].value - baseLine) * yStep + this.miniLayer.height / 2 + this.miniLayer.position.y,
          },
          value: this.miniLayer.data[this.miniLayer.data.length - 1].value,
          color: '#777777',
        };
        this.circle.setPosition(
          this.miniLayer.data.length * xStep,
          (this.miniLayer.data[this.miniLayer.data.length - 1].value - baseLine) * yStep + this.miniLayer.height / 2 + this.miniLayer.position.y
        );
        this.circleAction.setPosition(
          this.circle.position.x,
          this.circle.position.y,
        );
        this.currentPrice.make();
        this.axisLayer.make();
      }
    }, data);
    this.canvas.addChild(
      this.axisLayer,
      this.miniLayer,
      this.currentPrice,
      this.circleAction,
      this.circle
    );
    this.miniLayer.make();
    this.canvas.paint();
    OChart.on(`${id}:updateMinData`, this.updateRate);
  }

  componentWillUnmount() {
    const { id } = this.props;
    OChart.remove(`${id}:updateMinData`, this.updateRate)
  }

  render() {
    const { className = '' } = this.props;
    return (
      <div className={className} ref={this.chartRef}/>
    );
  }
}
